package com.xgame.controller;

import java.io.IOException;
import java.io.PrintWriter;
import java.util.Date;
import java.util.Map;

import javax.servlet.http.Cookie;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import org.apache.commons.httpclient.util.DateUtil;
import org.apache.commons.lang.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.util.Assert;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;
import org.springframework.web.servlet.ModelAndView;
import org.springframework.web.servlet.view.RedirectView;

import com.xgame.controller.type.UserTypeEnum;
import com.xgame.memcache.ICacheClient;
import com.xgame.mybatis.model.User;
import com.xgame.service.ClientService;
import com.xgame.service.UserService;
import com.xgame.util.AutoLoginKeyUtil;
import com.xgame.util.ObjectJsonUtil;
import com.xgame.util.VM;

public abstract class BaseController extends BaseLoginMethod {
	protected final Logger log = LoggerFactory.getLogger(getClass());
	@Autowired
	ICacheClient memcache;
	
	@Autowired
	UserService userService;
	
	@Autowired
	ClientService clientService;

	protected static final String ERROR_MSG_KEY = "errorMsg";
	protected static final String LKEY = "LKEY";
	protected static final String IP = "ip";
	/**
	 * 登录的页面 当访问需要登录的页面时，自动转到该页面
	 */
	private String loginUrl;

	public int LIST_PAGESIZE = 20;

	protected HttpServletRequest request;

	/**
	 * 操作完成后返回操作失败的JSON格式的数据
	 * 
	 * @param response
	 */
	protected void generateFail(HttpServletRequest request,
			HttpServletResponse response) {
		response.setContentType("application/json; charset=UTF-8");
		response.setHeader("Cache-Control", "no-cache");
		response.setCharacterEncoding("UTF-8");
		PrintWriter out;
		try {
			out = response.getWriter();
			String msg = "{\"errCode\":301,\"success\":false,\"msg\":\"登录失败\"}";
			log.info("登陆返回301." + request.getRequestURI());
			log.info("SID->" + request.getSession().getId());
			out.print(msg);
			out.close();
		} catch (IOException e) {
			e.printStackTrace();
		}
	}

	/**
	 * 从session里去user
	 */
	public User getLoginUser() {
		User user = (User) getRequest().getSession().getAttribute("USER");
		// if (user == null){
		// }
		return user;
	}

	public HttpServletRequest getRequest() {
		HttpServletRequest request = ((ServletRequestAttributes) RequestContextHolder
				.getRequestAttributes()).getRequest();
		return request;
	}

	// // ① 获取保存在Session中的用户对象
	// protected User getSessionUser(HttpServletRequest request) {
	// return (User) request.getSession().getAttribute("loginUser");
	// }
	//
	// // ②将用户对象保存到Session中
	// protected void setSessionUser(HttpServletRequest request, User user) {
	// request.getSession().setAttribute("loginUser", user);
	// }

	// ③ 获取基于应用程序的url绝对路径
	public final String getAppbaseUrl(HttpServletRequest request, String url) {
		Assert.hasLength(url, "url不能为空");
		Assert.isTrue(url.startsWith("/"), "必须以/打头");
		return request.getContextPath() + url;
	}

//	// 将手机对象保存到Session中
//	protected void setSessionClient(HttpServletRequest request,
//			LoginClient loginClient) {
//		request.getSession().setAttribute("loginClient", loginClient);
//	}

	/********************* 用户登录相关 *******************/
	/**
	 * 当前登录的帐号
	 */
	private User loginUser = null;

	/**
	 * 判断用户是否已经登录
	 * 
	 * @return
	 */
	protected boolean isLogged() {
		return this.getLoginUser() != null;
	}

	/**
	 * 跳转到登录页面
	 * 
	 * @return
	 */
	protected ModelAndView toLoginView() {
		return new ModelAndView(new RedirectView(this.loginUrl), "tourl", this
				.getRequest().getRequestURI());
	}

	/********************* 用户登录相关 *******************/

	/********************* 获取访问IP *******************/
	/**
	 * 获取远程访问IP
	 */
	private String remoteIp = null;

	/**
	 * 获取远程访问IP
	 * 
	 * @return
	 */
	protected String getRemoteIp() {
		HttpServletRequest request = this.getRequest();
		if (this.remoteIp == null || this.remoteIp.length() == 0) {
			this.remoteIp = request.getHeader("x-forwarded-for");
			if (this.remoteIp == null || this.remoteIp.isEmpty()
					|| "unknown".equalsIgnoreCase(this.remoteIp)) {
				this.remoteIp = request.getHeader("X-Real-IP");
			}
			if (this.remoteIp == null || this.remoteIp.isEmpty()
					|| "unknown".equalsIgnoreCase(this.remoteIp)) {
				this.remoteIp = request.getHeader("Proxy-Client-IP");
			}
			if (this.remoteIp == null || this.remoteIp.isEmpty()
					|| "unknown".equalsIgnoreCase(this.remoteIp)) {
				this.remoteIp = request.getHeader("WL-Proxy-Client-IP");
			}
			if (this.remoteIp == null || this.remoteIp.isEmpty()
					|| "unknown".equalsIgnoreCase(this.remoteIp)) {
				this.remoteIp = request.getHeader("HTTP_CLIENT_IP");
			}
			if (this.remoteIp == null || this.remoteIp.isEmpty()
					|| "unknown".equalsIgnoreCase(this.remoteIp)) {
				this.remoteIp = request.getHeader("HTTP_X_FORWARDED_FOR");
			}
			if (this.remoteIp == null || this.remoteIp.isEmpty()
					|| "unknown".equalsIgnoreCase(this.remoteIp)) {
				this.remoteIp = request.getRemoteAddr();
			}
			if (this.remoteIp == null || this.remoteIp.isEmpty()
					|| "unknown".equalsIgnoreCase(this.remoteIp)) {
				this.remoteIp = request.getRemoteHost();
			}
		}
		return remoteIp;
	}

	/********************* 获取访问IP *******************/
	/********************* 获取访问参数 *******************/
	/**
	 * 获取所有参数
	 * 
	 * @return
	 */
	protected Map<String, String[]> getParams() {
		HttpServletRequest request = this.getRequest();
		return request.getParameterMap();
	}

	/**
	 * 获取指定的配置
	 * 
	 * @param name
	 * @return
	 */
	protected String getParam(String name) {
		return getParam(name, "");
	}

	/**
	 * 根据参数名称获取参数值，如果没有找到则以默认值返回
	 * 
	 * @param name
	 * @param defaultValue
	 * @return
	 */
	protected String getParam(String name, String defaultValue) {
		HttpServletRequest request = this.getRequest();
		String strValue = request.getParameter(name);
		return strValue == null ? defaultValue : strValue;
	}

	/**
	 * 获取整形的参数值
	 * 
	 * @param name
	 * @param defaultValue
	 * @return
	 */
	protected int getIntParam(String name) {
		return getParam(name, 0);
	}

	/**
	 * 获取整形的参数值
	 * 
	 * @param name
	 * @param defaultValue
	 * @return
	 */
	protected int getParam(String name, Integer defaultValue) {
		String strValue = getParam(name, defaultValue.toString());
		try {
			return Integer.valueOf(strValue);
		} catch (Exception e) {
			return defaultValue;
		}
	}

	/**
	 * 获取长整形的参数值
	 * 
	 * @param name
	 * @param defaultValue
	 * @return
	 */
	protected long getLongParam(String name) {
		return getParam(name, 0L);
	}

	/**
	 * 获取长整形的参数值
	 * 
	 * @param name
	 * @param defaultValue
	 * @return
	 */
	protected long getParam(String name, Long defaultValue) {
		String strValue = getParam(name, defaultValue.toString());
		try {
			return Long.valueOf(strValue);
		} catch (Exception e) {
			return defaultValue;
		}
	}

	/**
	 * 获取单精度的参数值
	 * 
	 * @param name
	 * @param defaultValue
	 * @return
	 */
	protected float getFloatParam(String name) {
		return getParam(name, 0F);
	}

	/**
	 * 获取单精度的参数值
	 * 
	 * @param name
	 * @param defaultValue
	 * @return
	 */
	protected float getParam(String name, Float defaultValue) {
		String strValue = getParam(name, defaultValue.toString());
		try {
			return Float.valueOf(strValue);
		} catch (Exception e) {
			return defaultValue;
		}
	}

	/**
	 * 获取双精度的参数值
	 * 
	 * @param name
	 * @param defaultValue
	 * @return
	 */
	protected double getDoubleParam(String name) {
		return getParam(name, 0D);
	}

	/**
	 * 获取双精度的参数值
	 * 
	 * @param name
	 * @param defaultValue
	 * @return
	 */
	protected double getParam(String name, Double defaultValue) {
		String strValue = getParam(name, defaultValue.toString());
		try {
			return Double.valueOf(strValue);
		} catch (Exception e) {
			return defaultValue;
		}
	}

	/**
	 * 获取字节的参数值
	 * 
	 * @param name
	 * @param defaultValue
	 * @return
	 */
	protected byte getByteParam(String name) {
		return getParam(name, (byte) 0);
	}

	/**
	 * 获取字节的参数值
	 * 
	 * @param name
	 * @param defaultValue
	 * @return
	 */
	protected byte getParam(String name, Byte defaultValue) {
		String strValue = getParam(name, defaultValue.toString());
		try {
			return Byte.valueOf(strValue);
		} catch (Exception e) {
			return defaultValue;
		}
	}

	/**
	 * 获取字节的参数值
	 * 
	 * @param name
	 * @param defaultValue
	 * @return
	 */
	protected short getShortParam(String name) {
		return getParam(name, (short) 0);
	}

	/**
	 * 获取字节的参数值
	 * 
	 * @param name
	 * @param defaultValue
	 * @return
	 */
	protected short getParam(String name, Short defaultValue) {
		String strValue = getParam(name, defaultValue.toString());
		try {
			return Short.valueOf(strValue);
		} catch (Exception e) {
			return defaultValue;
		}
	}

	/**
	 * 获取布尔的参数值
	 * 
	 * @param name
	 * @param defaultValue
	 * @return
	 */
	protected boolean getBooleanParam(String name) {
		return getParam(name, false);
	}

	/**
	 * 获取布尔的参数值
	 * 
	 * @param name
	 * @param defaultValue
	 * @return
	 */
	protected boolean getParam(String name, Boolean defaultValue) {
		String strValue = getParam(name, defaultValue.toString());
		try {
			return Boolean.valueOf(strValue);
		} catch (Exception e) {
			return defaultValue;
		}
	}

	/**
	 * 获取日期的参数值
	 * 
	 * @param name
	 * @param defaultValue
	 * @return
	 */
	protected Date getDateParam(String name) {
		return getParam(name, new Date());
	}

	/**
	 * 获取日期的参数值
	 * 
	 * @param name
	 * @param defaultValue
	 * @return
	 */
	protected Date getParam(String name, Date defaultValue) {
		String strValue = getParam(name);
		if (strValue == null || strValue.length() == 0)
			return defaultValue;
		try {
			return DateUtil.parseDate(strValue);
		} catch (Exception e) {
			return defaultValue;
		}
	}

	/********************* 获取访问参数 *******************/
	/******************* 操作Cookie ********************/
	protected void savaLoginInfo(User user, HttpServletResponse response) {
		String key = AutoLoginKeyUtil.getLKey(user.getUserName(),
				user.getPassword());
		this.getRequest().getSession().setAttribute("LKEY", key);
		Cookie cookie = new Cookie("LKEY", key);
		cookie.setMaxAge(30 * 24 * 3600);// 30天
		cookie.setPath("/");
		response.addCookie(cookie);
	}

	protected void savaSid(String sid, HttpServletResponse response) {
		this.getRequest().getSession().setAttribute("SID", sid);
		Cookie cookie = new Cookie("SID", sid);
		cookie.setMaxAge(365 * 24 * 3600);// 365天
		cookie.setPath("/");
		response.addCookie(cookie);
	}

	/**
	 * 六小时注册数
	 * 
	 * @param ipValue
	 * @param response
	 */
	protected void savaIpNum(String ip, String ipValue,
			HttpServletResponse response) {
		this.getRequest().getSession().setAttribute(ip, ipValue);
		Cookie cookie = new Cookie(ip, ipValue);
		cookie.setMaxAge(VM.getInatance().getHour() * 60);// 6小时
		cookie.setPath("/");
		response.addCookie(cookie);
	}

	/**
	 * 获取指定键的Cookie
	 * 
	 * @param cookieName
	 * @return 如果找到Cookie则返回 否则返回null
	 */
	protected Cookie getCookie(String cookieName) {
		if (StringUtils.isEmpty(cookieName)
				|| this.getRequest().getCookies() == null)
			return null;
		for (Cookie cookie : this.getRequest().getCookies()) {
			System.out.println(cookie.getName());
			if (cookieName.equals(cookie.getName()))
				return cookie;
		}
		return null;
	}

	/**
	 * 获取指定键的Cookie值
	 * 
	 * @param cookieName
	 * @return 如果找到Cookie则返回 否则返回null
	 */
	protected String getCookieValue(String cookieName) {
		Cookie cookie = this.getCookie(cookieName);
		return cookie == null ? null : cookie.getValue();
	}

	/**
	 * 删除指定的Cookie
	 * 
	 * @param cookieName
	 */
	protected void removeCookie(String cookieName, HttpServletResponse response) {
		// HttpServletResponse response = this.getResponse();
		Cookie cookie = new Cookie(cookieName, null);
		cookie.setMaxAge(0);
		cookie.setPath("/");
		response.addCookie(cookie);
	}

	/**
	 * 保存一个对象到Cookie里 Cookie只在会话内有效
	 * 
	 * @param cookieName
	 * @param inst
	 */
	protected void setCookie(String cookieName, Object inst) {
		this.setCookie(cookieName, "/", inst);
	}

	/**
	 * 保存一个对象到Cookie Cookie只在会话内有效
	 * 
	 * @param cookieName
	 * @param path
	 * @param inst
	 */
	protected void setCookie(String cookieName, String path, Object inst) {
		if (StringUtils.isEmpty(cookieName) || inst == null)
			return;
		String strCookieString = this.object2CookieString(inst);
		this.setCookie(cookieName, path, strCookieString);
	}

	/**
	 * 保存一个对象到Cookie Cookie只在会话内有效
	 * 
	 * @param cookieName
	 * @param path
	 * @param cookieValue
	 */
	protected void setCookie(String cookieName, String path,
			String cookieValue, HttpServletResponse response) {
		// HttpServletResponse response = this.getResponse();
		if (StringUtils.isEmpty(cookieName) || cookieValue == null)
			return;
		Cookie cookie = new Cookie(cookieName, cookieValue);
		if (!StringUtils.isEmpty(path)) {
			cookie.setPath(path);
		}
		response.addCookie(cookie);
	}


	/**
	 * 把对象转换为Cookie存贮字串
	 * 
	 * @param inst
	 * @return
	 */
	private String object2CookieString(Object obj) {
		if (obj == null)
			return "";
		return ObjectJsonUtil.object2JsonString(obj);
	}

	/**
	 * 从Cookie中获对对象
	 * 
	 * @param cookieName
	 * @param inst
	 * @return 如果获取转换成功，则返回true, 否则返回false
	 */
	protected Object getCookieObject(String cookieName, Class<?> clazz) {
		String jsonStr = getCookieValue(cookieName);
		return ObjectJsonUtil.JsonStringToObj(jsonStr, clazz);
	}

	/**
	 * 是否是简单的数据类型
	 * 
	 * @param type
	 * @return
	 */
	@SuppressWarnings("unused")
	private boolean isSimpleProperty(Class<?> propType) {
		if (!propType.isPrimitive()
				&& !propType.isEnum()
				&& (!propType.equals(String.class) && !propType
						.equals(Date.class))) {
			return false;
		}
		return true;
	}

	/**
	 * 从memcache中获取user信息
	 * 
	 * @param sid
	 * @return
	 */
	User getUserFromMemcache() {
		String sid = getCookieValue(SID);
		Object o = memcache.get(sid);
		User user = null;
		if (o instanceof User) {
			user = (User) o;
		}
		return user;
	}

	/**
	 * memcache key exists delete
	 * 
	 * @param key
	 */
	void memcackeKeyExists(String key) {
		if (memcache.keyExists(key))
			memcache.delete(key);
	}

	/**
	 * 用户信息放入session中
	 * 
	 * @param user
	 */
	void setUserSession(User user) {
		this.getRequest().getSession().setAttribute("USER", user);
	}

	/**
	 * 從session中获取用户信息
	 * 
	 * @return
	 */
	User getUserSession(String userName) {
		Object o = this.getRequest().getSession().getAttribute("USER");
		if (o instanceof User)
			return (User) o;
		else {
			try {
				return userService.findUserByName(userName);
			} catch (Exception e) {
				return null;
			}
		}
	}

	/**
	 * 從session中获取用户信息
	 * 
	 * @return
	 */
	User getUserSession() {
		Object o = this.getRequest().getSession().getAttribute("USER");
		if (o instanceof User)
			return (User) o;
		else
			return null;
	}

	void toErrorPage(Exception e,Logger log,ModelAndView model){
		log.error(e.getLocalizedMessage(), e);
		getRequest().setAttribute("exception", e);
		model.setViewName("pages/error");
	}
	
	void toErrorPage(Logger log,ModelAndView model){
		Exception e=new Exception("参数错误！");
		log.error(e.getLocalizedMessage(), e);
		getRequest().setAttribute("exception", e);
		model.setViewName("pages/error");
	}
}
